<?php
/*
 * MiniMe - a minimalistic OStatus complient microblogging tool
 * Copyright (C) 2010, Tuomas Koski - koski.tuomas@gmail.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @author     Tuomas Koski <koski.tuomas@gmail.com>
 * @copyright  Tuomas Koski
 * @license    http://www.gnu.org/licenses/lgpl.txt
 */
class Magic_Signature_Verify {
    
    private $publicKey;
    
    private $modulus;
    private $exponent;
    
    public function __construct($encodedPublicKey) {
        $this->parseModulusExponentFromEncodedPublicKey($encodedPublicKey);
        $this->calculatePublicKey();
    }
    
    private function setModulus($modulus) {
        $this->modulus = $modulus;
    }
    
    private function setExponent($exponent) {
        $this->exponent = $exponent;
    }
    
    private function parseModulusExponentFromEncodedPublicKey($encodedPublicKey) {
        
         // remove whitespace
        $text = preg_replace('/\s+/', '', $encodedPublicKey);

        // parse components
        if (!preg_match('/RSA\.([^\.]+)\.([^\.]+)(.([^\.]+))?/', $text, $matches)) {
            return false;
        }
        
        $this->setModulus(Magic::base64_url_decode($matches[1]));
        $this->setExponent(Magic::base64_url_decode($matches[2]));
        
    }
    
    // Remove everything below here to own class.
    private function calculatePublicKey() {
        
        $rsa = new Crypt_RSA();
        $rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
        $rsa->setHash('sha256');
        $rsa->modulus = new Math_BigInteger($this->modulus, 256);
        $rsa->k = strlen($rsa->modulus->toBytes());
        $rsa->exponent = new Math_BigInteger($this->exponent, 256);
        
        $this->publicKey = $rsa;
    }
    
    public function dataHasValidSignature($signedData, $signature) {
        if(empty($this->publicKey)) {
            $this->parseModulusExponentFromMagicPublicKey();
            $this->calculatePublicKey();
        }
        return $this->publicKey->verify($signedData, $signature);
    }
    
    public function magicEnvelopeHasValidSignature(Magic_Envelope $magicEnvelope) {
        $signature = Magic::base64_url_decode($magicEnvelope->getSignature());
        return $this->publicKey->verify($magicEnvelope->getEncodedData(), $signature);
    }
}